package com.vert.db.impl;

import com.vert.annotations.Service;
import com.vert.c3p0.C3P0DataSource;
import com.vert.db.DBSql;
import com.vert.utils.DataSourceUtils;

import java.sql.*;
import java.sql.Date;
import java.util.*;

/**
 * @Classname DBSqlImpl
 * @Description TODO
 * @Date 2022/5/27 14:02
 * @Created by XiongXiong
 * @Author: X.I.O
 */
@Service
public class DBSqlImpl implements DBSql {



      @Override
      public List<Map<String, Object>> selectList(String sql) {
        return this.selectMapObjList(sql);
      }

      @Override
      public Map<String, Object> selectMaps(String sql) {
        return this.selectMapObj(sql);
      }

      @Override
      public boolean update(String sql) {
         return this.updateSql(sql);
      }

      @Override
      public boolean insert(String tableName, Map<String, Object> objectMap) {
        List<Object> objectList=null;
        objectList=new ArrayList<Object>();
        StringJoiner fields=null;
        fields=new StringJoiner(",","(",")");
        StringJoiner values=null;
        values=new StringJoiner(",","(",")");
        for (Map.Entry<String,Object> map : objectMap.entrySet()){
            if(map.getValue()==null ){
                continue;
            }
            fields.add(map.getKey());
            values.add("?");
            objectList.add(map.getValue());
        }
        StringBuilder sb = null;
        sb=new StringBuilder();
        sb.append("INSERT INTO ").append(tableName).append(" ").append(fields.toString()).append(" VALUES ").append(values.toString());
        this.insertObj(sb.toString(),objectList);
        return true;
      }

    private boolean updateSql(String sql){
            Connection connection=null;
            try {
              connection=getConnection();
              sqlExecute(sql,connection);
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                closeConnection(connection);
            }
            return true;
        }

      private Connection getConnection(){
          C3P0DataSource c3P0DataSource= DataSourceUtils.getC3P0DataSource();
          return c3P0DataSource.getConnection();
      }

      private void closeConnection(Connection connection){
          C3P0DataSource c3P0DataSource= DataSourceUtils.getC3P0DataSource();
          c3P0DataSource.clonse(connection);
          connection=null;
      }

      private List<Map<String, Object>> selectMapObjList(String sql) {
            Connection conn=this.getConnection();
            ResultSet resultSet = this.sqlExecuteQuery(sql,conn);
            List<Map<String, Object>> mapList = null;
            if (resultSet != null) {
              String[] fields = this.getFeildList(resultSet);
              try {
                mapList = new ArrayList(50);
                while(resultSet.next()) {
                  Map<String, Object> stringObjectMap = new HashMap();
                  for(int i = 0; i < fields.length; ++i) {
                    String feildName = fields[i];
                    Object value = resultSet.getObject(feildName);

                    stringObjectMap.put(feildName, value);
                  }
                  mapList.add(stringObjectMap);
                }
              } catch (Exception var12) {
                var12.printStackTrace();
              }finally {
                  closeConnection(conn);
              }
              return mapList;
            } else {
              return mapList;
            }
      }

      private int insert(String sql){
          Connection conn = null;
           PreparedStatement sta=null;
          try {
              conn=getConnection();
              sta=conn.prepareStatement(sql);
              int rows = sta.executeUpdate();
             return rows;
          }catch (Exception var12) {
              var12.printStackTrace();
          }
          return 0;
      }

      private int insertObj(String sql,List<Object> list){
        PreparedStatement sta=null;
        Connection conn = null;
        try{
            conn = getConnection();
            sta=conn.prepareStatement(sql);
            for (int i = 0; i < list.size(); i++) {
                Object obj=list.get(i);
                int num=i+1;
                insertDealObject(sta,num,obj);
            }
            int rows = sta.executeUpdate();
            if(rows > 0) {
              System.out.println("operate successfully!");
            }
            return rows;
        }catch (Exception e){
          e.printStackTrace();
        }finally {
            closeConnection(conn);
        }
        return 0;
      }

      private void insertDealObject(PreparedStatement sta,Integer num,Object obj) throws SQLException {
        if(obj instanceof String){
          sta.setString(num,(String) obj);
        }
        if(obj instanceof Integer){
          sta.setInt(num,(int)obj);
        }
        if(obj instanceof Double){
          sta.setDouble(num,(Double)obj);
        }
        if(obj instanceof  Float){
          sta.setFloat(num,(Float)obj);
        }
        if(obj instanceof Date){
          sta.setDate(num,(Date)obj);
        }
        if(obj instanceof Blob){
            sta.setBlob(num,(Blob)obj);
        }
      }


  private List<String> selectStringList(String sql){
        Connection conn = getConnection();
        ResultSet resultSet = this.sqlExecuteQuery(sql,conn);
        List<String> mapList = null;
        if (resultSet != null ) {
          String[] fields = this.getFeildList(resultSet);
          try {
            mapList = new ArrayList(50);
            while(resultSet.next()) {
              String str=null;
              for(int i = 0; i < fields.length; ++i) {
                String feildName = fields[i];
                Object value = resultSet.getObject(feildName);
                if(value!=null){
                  str=String.valueOf(value);
                }
              }
              if(str!=null){
                mapList.add(str);
              }
            }
          } catch (Exception var12) {
              var12.printStackTrace();
          }finally {
              closeConnection(conn);
          }
          return mapList;
        } else {
          return mapList;
        }
      }


      public Map<String, Object> selectMapObj(String sql) {
            Map<String, Object> objectMap = null;
            Connection connection=getConnection();
            ResultSet resultSet = this.sqlExecuteQuery(sql,connection);
            if (resultSet == null) {
              return objectMap;
            } else {
              String[] fields = this.getFeildList(resultSet);
              try {
                if (resultSet.next()) {
                  objectMap = new HashMap(1);
                  for(int i = 0; i < fields.length; ++i) {
                    String feildName = fields[i];
                    Object value = resultSet.getObject(feildName);
                    objectMap.put(feildName, value);
                  }
                  return objectMap;
                }
              } catch (Exception var11) {
                var11.printStackTrace();
              }finally {
                  closeConnection(connection);
              }
              return objectMap;
            }
    }


        private String[] getFeildList(ResultSet rs) {
          try {
            ResultSetMetaData rsmd = rs.getMetaData();
            String[] lie = new String[rsmd.getColumnCount()];
            for(int i = 1; i < rsmd.getColumnCount() + 1; ++i) {
              lie[i - 1] = rsmd.getColumnName(i);
            }
            return lie;
          } catch (Exception var5) {
            var5.printStackTrace();
            return new String[0];
          }
        }

      private ResultSet sqlExecuteQuery(String sql,Connection conn) {
          Statement stmt = null;
          ResultSet rs = null;
          try {
            if (conn == null) {
              return null;
            } else {
              stmt = conn.createStatement();
              rs = stmt.executeQuery(sql);
              return rs;
            }
          } catch (Exception var5) {
            var5.printStackTrace();
            return rs;
          }
      }

      private boolean sqlExecute(String sql,Connection conn) {
        boolean flag = false;
        Statement stmt = null;
        try {
          stmt = conn.createStatement();
          flag = stmt.execute(sql);
          return flag;
        } catch (Exception var8) {
          var8.printStackTrace();
        }
        return flag;
      }
}
